package com.ghp.admin.handler;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.ghp.admin.service.UserInterfaceInfoService;
import com.ghp.common.api.InnerUserInterfaceInfoService;
import com.ghp.common.model.entity.UserInterfaceInfo;
import com.ghp.sms.constants.SmsEmailRequestTypeEnum;
import com.ghp.sms.utils.CaptchaGenerator;
import com.ghp.sms.utils.SmsEmailUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

import static com.ghp.common.constants.MessageQueueConstants.*;
import static com.ghp.common.constants.RedisConstants.LOGIN_CAPTCHA_KEY;
import static com.ghp.common.constants.RedisConstants.LOGIN_CAPTCHA_TTL;

/**
 * @author ghp
 * @title
 * @description
 */
@Slf4j
@Component
public class MessageQueueHandler {
    @Resource
    private RedisTemplate redisTemplate;

    @Resource
    private RabbitTemplate rabbitTemplate;

    @Resource
    private InnerUserInterfaceInfoService innerUserInterfaceInfoService;

    @Resource
    private UserInterfaceInfoService userInterfaceInfoService;



    /**
     * 创建一个队列，专门用于更新接口调用次数
     */
    @PostConstruct
    public void createQueue() {
        rabbitTemplate.execute(channel -> {
            channel.queueDeclare(QUEUE_INTERFACE_CALL_NUMBER, true, false, false, null);
            return null;
        });
    }

    /**
     * 更新接口调用次数
     */
    @RabbitListener(queues = QUEUE_INTERFACE_CALL_NUMBER)
    public void interfaceCallNumberHandler(String userIdAndInterfaceId) {
        UserInterfaceInfo userInterfaceInfo = innerUserInterfaceInfoService.checkLeftNum(userIdAndInterfaceId);
        Long userId = userInterfaceInfo.getUserId();
        Long interfaceInfoId = userInterfaceInfo.getInterfaceInfoId();
        Integer leftNum = userInterfaceInfo.getLeftNum();
        Integer totalNum = userInterfaceInfo.getTotalNum();
        if (leftNum <= 0) {
            return;
        }
        try {
            userInterfaceInfoService.update(new LambdaUpdateWrapper<UserInterfaceInfo>()
                    .eq(UserInterfaceInfo::getInterfaceInfoId, interfaceInfoId)
                    .eq(UserInterfaceInfo::getUserId, userId)
                    // 只有当剩余调用次数 > 0时才进行扣减
                    .gt(UserInterfaceInfo::getLeftNum, 0)
                    .set(UserInterfaceInfo::getTotalNum, totalNum + 1)
                    .set(UserInterfaceInfo::getLeftNum, leftNum - 1));
        } catch (Exception e) {
            // 将消费失败的消息添加到死信队列中
            rabbitTemplate.convertAndSend(DEAD_QUEUE_INTERFACE_CALL_NUMBER, interfaceInfoId);
        }
    }


    /**
     * 处理死信队列中的消息
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = DEAD_QUEUE_INTERFACE_CALL_NUMBER, durable = "true"),
            exchange = @Exchange(name = DEAD_EXCHANGE_INTERFACE_CALL_NUMBER, type = ExchangeTypes.TOPIC),
            key = DEAD_ROUTING_KEY_INTERFACE_CALL_NUMBER
    ))
    public void deadInterfaceCallNumberHandler(String userIdAndInterfaceId) {
        while (true) {
            UserInterfaceInfo userInterfaceInfo = innerUserInterfaceInfoService.checkLeftNum(userIdAndInterfaceId);
            Long userId = userInterfaceInfo.getUserId();
            Long interfaceInfoId = userInterfaceInfo.getInterfaceInfoId();
            Integer leftNum = userInterfaceInfo.getLeftNum();
            Integer totalNum = userInterfaceInfo.getTotalNum();
            if (leftNum <= 0) {
                break;
            }
            try {
                userInterfaceInfoService.update(new LambdaUpdateWrapper<UserInterfaceInfo>()
                        .eq(UserInterfaceInfo::getInterfaceInfoId, interfaceInfoId)
                        .eq(UserInterfaceInfo::getUserId, userId)
                        // 只有当剩余调用次数 > 0时才进行扣减
                        .gt(UserInterfaceInfo::getLeftNum, 0)
                        .set(UserInterfaceInfo::getTotalNum, totalNum + 1)
                        .set(UserInterfaceInfo::getLeftNum, leftNum - 1));
            } catch (Exception e) {
                log.error("处理死信发生异常");
            }
        }
    }

    /**
     * 处理短信队列中的消息
     */
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = QUEUE_CAPTCHA, durable = "true"),
            exchange = @Exchange(name = EXCHANGE_CAPTCHA, type = ExchangeTypes.TOPIC),
            key = ROUTING_KEY_CAPTCHA
    ))
    public void sendCaptchaHandler(String phoneOrEmail) {
        String captcha = CaptchaGenerator.generateNumericCaptcha(6);
        SmsEmailUtils.sendCaptcha(SmsEmailRequestTypeEnum.ALIYUN, SmsEmailRequestTypeEnum.QQ,
                phoneOrEmail, captcha);
        // 短信发送后，将验证码保存到Redis
        redisTemplate.opsForValue().set(LOGIN_CAPTCHA_KEY + phoneOrEmail, captcha,
                LOGIN_CAPTCHA_TTL, TimeUnit.SECONDS);
    }
}
